home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 040 (1987-11-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 040 (1987-11-15)(Ossowski, Stefan)(DE)(PD).adf / A68k / A68kmisc.c < prev    next >
C/C++ Source or Header  |  1989-01-18  |  21KB  |  739 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*              MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*          Copyright    (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*        Miscellaneous routines - September 8, 1987            */
  8. /*                                    */
  9. /*   This program may be copied    for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on    all copies of the source code.    Copying    for any    other use   */
  12. /*   without the consent of the    author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*    AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs.    */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. #include <stdio.h>
  24. #include "a68kdef.h"
  25. #include "a68kglb.h"
  26.  
  27. char Sdata[MAXSREC];    /* S-record data */
  28. int  Sindex;        /* Index for Sdata */
  29. int  NumRExt, NumR32, NumR16, NumR8;
  30.  
  31. static char *errmsg[] =    {
  32.     "--- Unknown error code ---",
  33.     "Identifier too long -- Truncated!",
  34.     "No such op-code.",
  35.     "Duplicate Symbol.",
  36.     "Undefined Symbol.",
  37.     "Addressing mode not allowed here.",
  38.     "Error in operand format.",
  39.     "Error in relative branch.",
  40.     "Address mode error.",
  41.     "Operand size error.",
  42.     "END statement is missing.",
  43.     "Value must be absolute.",
  44.     "Relocatability error.",
  45.     "Too many nested INCLUDEs.",
  46.     "INCLUDE file cannot be opened.",
  47.     "Illegal forward reference.",
  48.     "Not supported in S-format.",
  49.     "This instruction needs a label.",
  50.     "Pass 1 / Pass 2 phase error.",
  51.     "ENDM statement is missing.",
  52.     "Too much DC data.",
  53.     "Too many SECTIONs.",
  54.     "Section may not be unnamed.",
  55.     "Wrong type in continuation.",
  56.     "Duplicate macro definition.",
  57.     ""};
  58.  
  59. /* Functions */
  60. extern int  LineParts(), GetField(), Instructions(), ObjDir();
  61. extern int  GetSize(), GetInstModeSize(), GetMultReg();
  62. extern int  ReadSymTab(), GetArgs(), GetAReg(),    OpenIncl();
  63. extern long GetValue(),    CalcValue();
  64. extern char *malloc();
  65. extern FILE *fopen();
  66.  
  67. long AddrBndW(), AddrBndL();
  68.  
  69.  
  70.  
  71. long AddrBndW (v) long v;
  72. /* Advances "v" to the next word boundary */
  73. {
  74.     if (v & 1L)    {
  75.     AppendSdata (Srec, 0L, 1);
  76.     v++;
  77.     }
  78.     return (v);
  79. }
  80.  
  81.  
  82.  
  83. long AddrBndL (v) long v;
  84. /* Advances "v" to the next long-word boundary */
  85. {
  86.     long templong;
  87.  
  88.     v =    AddrBndW (v);        /* Bump    to word    boundary first */
  89.     if (v & 2L)    {        /* If still not    aligned, */
  90.     templong = NOP;        /*  generate a NOP */
  91.     AppendSdata (Srec, templong, 2);
  92.     v += 2;
  93.     }
  94.     return (v);
  95. }
  96.  
  97.  
  98.  
  99. WriteListLine (f) FILE *f;
  100. /* Writes one line to the Listing file,    including Object Code */
  101. {
  102.     register int i, j;
  103.     long templong;
  104.     char macflag;
  105.  
  106.     if (errlim == 0)
  107.     if ((Dir == Page) || (Dir == Space) || (Dir == Title)
  108.     || (Dir    == DoList) || (Dir == NoList) || (ListOff))
  109.         return;        /* Don't print unless they have errors */
  110.  
  111.     CheckPage (f, FALSE);    /* Print headings if necessary */
  112.  
  113.     if (PrntAddr) {
  114.     if ((Dir == Equ) || (Dir == Set))
  115.         LongPut (f,    ObjSrc,    3);    /* Equated value */
  116.     else
  117.         LongPut (f,    AddrCnt, 3);    /* Current location */
  118.     fprintf    (f, "  ");
  119.     } else
  120.     fprintf    (f, "        ");        /* Don't print location */
  121.     LongPut (f,    ObjOp, nO);        /* Generated code */
  122.     if (nS != 0) {
  123.     fprintf    (f, " ");
  124.     LongPut    (f, ObjSrc, nS);
  125.     }
  126.     if (nD != 0) {
  127.     fprintf    (f, " ");
  128.     LongPut    (f, ObjDest, nD);
  129.     }
  130.     if ((j = nX) > 0) {                /* String data */
  131.     if ((j + nO + nS + nD) > 12)
  132.         j =    12 - nO    - nS - nD;
  133.     for (i = 0; i <    j; i++)    {
  134.         templong = ObjString[i];
  135.         LongPut (f,    templong, 1);
  136.     }
  137.     }
  138.     i =    6 + (nO    + nS + nD + j) * 2;    /* Hex digits printed */
  139.     if (nS != 0) i++;            /* Space between operands */
  140.     if (nD != 0) i++;
  141.     while (i < ObjMAX) {
  142.     fprintf    (f, " ");
  143.     i++;
  144.     }
  145.     if ((InFNum    == 0) || (OuterMac == 0))
  146.     macflag    = ' ';                  /* Open code */
  147.     else if (InFNum > OuterMac)
  148.     macflag    = '+';                  /* Inner macro */
  149.     else if ((InFNum ==    OuterMac) && (Dir != MacCall))
  150.     macflag    = '+';                  /* Outermost macro */
  151.     else
  152.     macflag    = ' ';                  /* We're outside macros */
  153.  
  154.     fprintf (f,    " %4d%c%s\n", LineCount, macflag, Line);
  155.  
  156.     for    (i = 0;    i < errlim; i++) {    /* Write error messages. */
  157.     CheckPage (f, FALSE);
  158.     fprintf    (f, "%s", errmsg[errcode[i]]);
  159.     for (j=strlen(errmsg[errcode[i]]); j<ObjMAX+8+errpos[i]; j++)
  160.         fprintf (f,    " ");
  161.     fprintf    (f, "^ ");              /* Error flag */
  162.     if (i == 0) {
  163.         if (InF->UPtr == 0)
  164.         fprintf    (f, "%s", InF->NPtr);       /* Module name */
  165.         else
  166.         fprintf    (f, "(user macro)");        /* In a user macro */
  167.         fprintf (f,    " line %d", InF->Line);     /* Line number */
  168.     }
  169.     fprintf    (f, "\n");
  170.     }
  171. }
  172.  
  173.  
  174.  
  175. WriteSymTab (f)    FILE *f;
  176. /* Lists symbol    table in alphabetical order */
  177. {
  178.     int     printhunk, i;
  179.     char *p;
  180.     register int j, k;
  181.     struct SymTab *sym;
  182.     struct Ref      *ref;
  183.  
  184.     LnCnt = 999;            /* Skip    to a new page. */
  185.     for    (i = 0,    sym = SymStart;    i < NumSyms; i++, sym++) {
  186.     CheckPage (f, TRUE);
  187.  
  188.     p = sym->Nam;            /* Pointer to symbol */
  189.     while (*p == ' ')               /* Skip leading blanks, if any */
  190.         p++;
  191.     fprintf    (f, "%-11s ", p);       /* Symbol or macro name */
  192.     if (strlen (p) > 11)        /* Long    symbol - go to new line    */
  193.         fprintf (f,    "\n            ");
  194.  
  195.     printhunk = FALSE;        /* Assume no hunk no. to print */
  196.     if (sym->Defn == 0)
  197.         fprintf (f,    "  *** UNDEFINED *** ");
  198.     else if    (sym->Flags & 4)
  199.         fprintf (f,    "  -- SET Symbol --  ");
  200.     else if    (sym->Flags & 8)
  201.         fprintf (f,    " +++ MACRO +++  %4d", sym->Defn);
  202.     else if    (sym->Flags & 0x10) {
  203.         fprintf (f,    " SECTION  ");
  204.         printhunk =    TRUE;
  205.     } else if (sym->Flags &    0x20) {
  206.         fprintf (f,    "      %c", (sym->Val & 8) ? 'A' : 'D');
  207.         fprintf (f,    "%d  ", sym->Val & 7);
  208.         printhunk =    TRUE;
  209.     } else {
  210.         LongPut (f,    sym->Val, 4);        /* Value */
  211.         fprintf (f,    "  ");
  212.         printhunk =    TRUE;
  213.     }
  214.     if (printhunk) {
  215.         j =    sym->Hunk & 0x00007FFFL;    /* Hunk    number */
  216.         if (sym->Flags & 0x60)
  217.         fprintf    (f, " Reg");            /* Register or list */
  218.         else if (sym->Hunk & 0x00008000L)
  219.         fprintf    (f, " Ext");            /* External */
  220.         else if (j == ABSHUNK)
  221.         fprintf    (f, " Abs");            /* Absolute */
  222.         else
  223.         fprintf    (f, "%4d", j);          /* Hunk number */
  224.         fprintf (f,    "  %4d", sym->Defn);    /* Statement no. */
  225.     }
  226.     if (XrefList) {
  227.         fprintf (f,    "  ");
  228.         if (sym->Ref1 == 0)
  229.         fprintf    (f, " *** UNREFERENCED ***");
  230.         else {
  231.         ref = sym->Ref1;
  232.         j = k =    0;
  233.         while (1) {
  234.             if (ref->RefNum[j] == 0)
  235.             break;
  236.             if (k >= 9)    {
  237.             fprintf    (f, "\n");              /* New line */
  238.             for (k = 0; k <    34; k++)
  239.                 fprintf (f,    " ");
  240.             k = 0;
  241.             }
  242.             fprintf (f,    " %4d", ref->RefNum[j]);
  243.             j++;
  244.             k++;
  245.             if (j < MAXREF)
  246.             continue;        /* Get the next    slot */
  247.             if ((ref = ref->NextRef) ==    0)
  248.             break;            /* End of last entry */
  249.             j =    0;            /* Start the next entry    */
  250.         }
  251.         }
  252.     }
  253.     fprintf    (f, "\n");
  254.     }
  255. }
  256.  
  257.  
  258.  
  259. CheckPage (f, xhdr) FILE *f; int xhdr;
  260. /* Checks if end of page reached yet --    if so, advances    to next    page. */
  261. {
  262.     LnCnt++;
  263.     if (LnCnt >= LnMax)    {
  264.     PgCnt++;
  265.     if (PgCnt > 1)
  266.         fprintf (f,    "\f");                  /* Skip to new page */
  267.     fprintf    (f, "%-50s", TTLstring);        /* Title */
  268.     fprintf    (f, "  %s        ", SourceFN);  /* File name */
  269.     fprintf    (f, "Page %d\n\n\n", PgCnt);    /* Page number */
  270.     LnCnt =    3;
  271.     if (xhdr) {
  272.         fprintf (f,    "Symbol       Value    Hunk  Line");
  273.         if (XrefList)
  274.         fprintf    (f, "   References");   /* Cross-reference */
  275.         fprintf (f,    "\n\n");
  276.         LnCnt += 2;
  277.     }
  278.     }
  279. }
  280.  
  281.  
  282.  
  283. StartSrec (f, idntname)    FILE *f; char idntname[];
  284. /* Writes object header    record */
  285. {
  286.     register int i;
  287.     long CheckSum, templong;
  288.  
  289.     if (SFormat) {
  290.     fprintf    (f, "S0");
  291.     templong = strlen (idntname) + 3; /* extra for addr. & checksum    */
  292.     LongPut    (f, templong, 1);
  293.     CheckSum = templong;
  294.  
  295.     fprintf    (f, "0000");  /* Address is 4 digits, all zero, for S0 */
  296.  
  297.     for (i = 0; idntname[i]    != '\0'; i++) {
  298.         templong = toupper (idntname[i]);
  299.         LongPut (f,    templong, 1);
  300.         CheckSum +=    templong;
  301.     }
  302.     CheckSum = ~CheckSum;        /* Complement checksum */
  303.     LongPut    (f, CheckSum, 1);
  304.     fprintf    (f, "\n");
  305.     } else {
  306.     templong = HunkUnit;
  307.     putl (f, templong);
  308.     DumpName (f, idntname, 0L);
  309.     }
  310.     StartAddr =    TempAddr = Sindex = 0;
  311.     NumRExt = NumR32 = NumR16 =    NumR8 =    0;
  312. }
  313.  
  314.  
  315.  
  316. WriteSrecLine (f) FILE *f;
  317. /* Transfers object code components to output buffer. */
  318. /* Moves long words or portions    thereof. */
  319. {
  320.     register int i;
  321.     long templong;
  322.  
  323.     if (HunkType == HunkBSS)
  324.     return;                /* No code in BSS hunk */
  325.  
  326.     if (nO + nS    + nD + nX) {        /* If we have object code */
  327.     if (AddrCnt < TempAddr)    {    /*  and    location counter jumped    */
  328.         if (SFormat)        /*  and    we're making S-format, */
  329.         DumpSdata (f);        /*  get    rid of what we have */
  330.         StartAddr =    TempAddr = AddrCnt;    /*  and    start afresh. */
  331.     }
  332.     while (AddrCnt >= (TempAddr + 4))    /* It jumped forward - */
  333.         AppendSdata    (f, 0L,    4);        /*  fill with zeros    */
  334.     if (AddrCnt > TempAddr)    {
  335.         i =    AddrCnt    - TempAddr;
  336.         AppendSdata    (f, 0L,    i);
  337.     }
  338.     AppendSdata (f,    ObjOp, nO);        /* Op code */
  339.     AppendSdata (f,    ObjSrc,    nS);        /* Source */
  340.     AppendSdata (f,    ObjDest, nD);        /* Destination */
  341.     for (i = 0; i <    nX; i++) {        /* String data */
  342.         templong = ObjString[i];
  343.         AppendSdata    (f, templong, 1);
  344.     }
  345.     }
  346. }
  347.  
  348.  
  349.  
  350. AppendSdata (f,    Data, n) FILE *f; long Data; int n;
  351. /* If we are producing S-format    records:
  352.      Transfers "n" low-order bytes from "Data" to the output buffer.
  353.      If    the buffer becomes full, DumpSdata will    be called to flush it.
  354.      S-records will also be broken on 16-byte boundaries.
  355.    If we are producing AmigaDOS    format,    data will be written
  356.      directly to Srec -    we'll go back and fill in the hunk length
  357.      at    the end    of the hunk.                    */
  358. {
  359.     register int  i;
  360.     register char byte;
  361.     long templong;
  362.  
  363.     if (!Pass2)
  364.     return;            /* Pass    2 only */
  365.     if (HunkType == HunkBSS)
  366.     return;            /* No data in BSS hunks! */
  367.  
  368.     if (HunkType == HunkNone) {    /* We're not in a hunk yet - */
  369.     ReadSymTab ("  ");      /*  set up pointer */
  370.     Sect = Sym;        /*  to the first section */
  371.     HunkType = HunkCode;    /*  (start a code hunk)    */
  372.     SectLine = LineCount;
  373.     if (!SFormat) {
  374.         templong = HunkName;
  375.         putl (f, templong);
  376.         DumpName (f, " ", 0L);
  377.         putl (f, HunkType);
  378.         LenPos = ftell (f);    /* Hunk    length goes here when we get it    */
  379.         putl (f, 0L);    /* For now, set    it to zero */
  380.     }
  381.     }
  382.  
  383.     Data <<= (4    - n) * 8;    /* Left-justify    data */
  384.  
  385.     for    (i = 0;    i < n; i++) {
  386.     byte = (Data >>    ((3 - i) * 8)) & 0x00FF;
  387.     TempAddr++;
  388.     if (!SFormat)
  389.         putc (byte,    f);
  390.     else {
  391.         Sdata[Sindex++] = byte;
  392.         if (((TempAddr & 0x0F) == 0) || (Sindex >= MAXSREC))
  393.         DumpSdata (f);        /* Break S-record */
  394.     }
  395.     }
  396. }
  397.  
  398.  
  399.  
  400. DumpSdata (f) FILE *f;
  401. /* Writes an object code record    */
  402. {
  403.     register int  i;
  404.     register long CheckSum, templong;
  405.  
  406.     if (!SFormat) {
  407.     AddrCnt    = AddrBndL (AddrCnt);    /* Finish last long word */
  408.     fseek (f, LenPos, 0);    /* Hunk    length field is    here */
  409.     putl (f, ((AddrCnt - SectStart)    >> 2) |    HunkFlags);
  410.     fseek (f, 0L, 2);    /* Back    to end of file */
  411.     DumpRel    (f);        /* Write relocation information    */
  412.     TempAddr = AddrCnt;
  413.     return;
  414.     }
  415.  
  416.     if (Sindex == 0)
  417.      return;        /* There's nothing to dump */
  418.  
  419.     fprintf (f,    "S2");
  420.     templong = Sindex +    4;    /* Record length */
  421.     LongPut (f,    templong, 1);
  422.     CheckSum = templong;    /* Initialize CheckSum */
  423.  
  424.     LongPut (f,    StartAddr, 3);    /* Address */
  425.     CheckSum +=    (StartAddr >> 16) & 0x00FF;
  426.     CheckSum +=    (StartAddr >> 8) & 0x00FF;
  427.     CheckSum +=    StartAddr & 0x00FF;
  428.  
  429.     for    (i = 0;    i < Sindex; i++) {
  430.     templong = Sdata[i];
  431.     LongPut    (f, templong, 1);    /* Object code */
  432.     CheckSum += templong;
  433.     }
  434.     CheckSum = ~CheckSum;    /* Complement checksum */
  435.     LongPut (f,    CheckSum, 1);
  436.     fprintf (f,    "\n");
  437.  
  438.     StartAddr += Sindex;
  439.     TempAddr = StartAddr;
  440.     Sindex = 0;
  441. }
  442.  
  443.  
  444.  
  445. PutRel (f, addr, hunk, size) FILE *f; long addr, hunk; int size;
  446. /* Build a relocation entry if necessary */
  447. {
  448.     struct RelTab *rel;
  449.  
  450.     if (!Pass2)    return;            /* Pass    2 only */
  451.     if (SFormat) return;        /* Not for S-format! */
  452.     if (hunk ==    ABSHUNK) return;    /* Absolute */
  453.     if (HunkType == HunkBSS) return;    /* Not for BSS hunks! */
  454.  
  455.     HeapSpace (sizeof(struct RelTab));    /* Make    sure we    have room */
  456.     rel    = (struct RelTab *) HeapLim;    /* Pointer to new entry    */
  457.     rel->Offset    = addr;            /* Offset */
  458.     rel->Hunk =    hunk;            /* Hunk    number */
  459.     rel->Size =    size;            /* Size    */
  460.     HeapLim += sizeof(struct RelTab);    /* Bump    heap limit pointer */
  461.  
  462.     if (hunk < 0)            /* Count entries by type */
  463.     NumRExt++;
  464.     else if (size == Long)
  465.     NumR32++;
  466.     else if (size == Word)
  467.     NumR16++;
  468.     else
  469.     NumR8++;
  470. }
  471.  
  472.  
  473.  
  474. DumpRel    (f) FILE *f;
  475. /* Dump    relocation information to the object file. */
  476. {
  477.     register struct SymTab *sym;
  478.     register struct RelTab *rel, *rel2;
  479.     int     i, j, size, num, donexhdr, secthlin;
  480.     long currhunk, nexthunk, templong;
  481.     char *p;
  482.  
  483.     if (SFormat)
  484.     return;                /* S-format is absolute! */
  485.  
  486.     secthlin = LineCount;        /* Current section ends    here */
  487.     if (strcmp (OpCode,"SECTION") == 0) /*   unless we're starting   */
  488.     secthlin--;            /*    a new section.         */
  489.  
  490.     while (1) {
  491.     if ((num = NumR32) != 0) {
  492.         size = Long;        /* Do 32-bit fields */
  493.         templong = HunkR32;
  494.         NumR32 = 0;            /* ...but only once */
  495.     } else if ((num    = NumR16) != 0)    {
  496.         size = Word;        /* Then    do 16-bit fields */
  497.         templong = HunkR16;
  498.         NumR16 = 0;
  499.     } else if ((num    = NumR8) != 0) {
  500.         size = Byte;        /* Finally do 8-bit fields */
  501.         templong = HunkR8;
  502.         NumR8 = 0;
  503.     } else
  504.         break;            /* We're all done */
  505.  
  506.     putl (f, templong);        /* Record type */
  507.  
  508.     currhunk = 32767;
  509.     num = 0;
  510.     for (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
  511.         if ((rel->Size == size) && (rel->Hunk >= 0)) {
  512.         if (rel->Hunk <    currhunk) {
  513.             currhunk = rel->Hunk;    /* Lowest hunk number */
  514.             num    = 1;            /* Reset counter */
  515.         } else if (rel->Hunk ==    currhunk) {
  516.             num++;            /* Count entries */
  517.         }
  518.         }
  519.     }
  520.     while (num > 0)    {    /* Repeat for all hunk references */
  521.         templong = num;
  522.         putl (f, templong);        /* Number of entries */
  523.         putl (f, currhunk);        /* Hunk    number */
  524.         nexthunk = 32767;
  525.         num    = 0;            /* Count for next hunk */
  526.         for    (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
  527.         if ((rel->Size == size)    && (rel->Hunk >= 0)) {
  528.             if (rel->Hunk < currhunk)
  529.             continue;        /* Already wrote it */
  530.             else if (rel->Hunk == currhunk)
  531.             putl (f, rel->Offset - Sect->Val);
  532.             else if (rel->Hunk < nexthunk) {
  533.             nexthunk = rel->Hunk;    /* Next    hunk number */
  534.             num = 1;        /* Reset counter */
  535.             } else if (rel->Hunk == nexthunk) {
  536.             num++;            /* Count entries */
  537.             }
  538.         }
  539.         }
  540.         currhunk = nexthunk;    /* Get ready for next hunk */
  541.     }
  542.     putl (f, 0L);        /* End of relocation information */
  543.     }
  544.  
  545.     donexhdr = FALSE;        /* Haven't written hunk_ext yet */
  546.  
  547.     for    (i = 0,    sym = SymStart;    i < NumSyms; i++, sym++) {
  548.     if (sym->Flags & 2) {        /* Scan    for XDEF symbols */
  549.         j =    sym->Defn;    /* Defined in current section? */
  550.         if ((j >= SectLine)    && (j <= secthlin)) {
  551.         if (!donexhdr) {
  552.             templong = HunkExt;    /* Haven't done header yet */
  553.             putl (f, templong);
  554.             donexhdr = TRUE;
  555.         }
  556.         if ((sym->Hunk & 0x0000FFFFL) == ABSHUNK)
  557.             templong = 0x02000000;
  558.         else
  559.             templong = 0x01000000;        /* Flags */
  560.         DumpName (f, sym->Nam, templong);    /* Symbol */
  561.         putl (f, sym->Val - Sect->Val);        /* Offset */
  562.         }
  563.     }
  564.     }
  565.  
  566.     if (NumRExt    != 0) {            /* External references (XREF) */
  567.     if (!donexhdr) {
  568.         templong = HunkExt;        /* Haven't done header yet */
  569.         putl (f, templong);
  570.         donexhdr = TRUE;
  571.     }
  572.     for (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
  573.         if (rel->Hunk < 0) {
  574.         p = Heap + ~rel->Hunk;
  575.         if (rel->Size == Long)
  576.             templong = 0x81000000;    /* ext_ref32 */
  577.         else if    (rel->Size == Word)
  578.             templong = 0x83000000;    /* ext_ref16 */
  579.         else
  580.             templong = 0x84000000;    /* ext_ref8 */
  581.         DumpName (f, p,    templong);    /* Flags and symbol */
  582.         templong = 1;
  583.         for (rel2 = rel    + 1; rel2 < (struct RelTab *) HeapLim; rel2++)
  584.             if (rel2->Hunk == rel->Hunk)
  585.             templong++;        /* Number of times */
  586.         putl (f, templong);        /*  symbol occurs  */
  587.         for (rel2 = rel; rel2 <    (struct    RelTab *) HeapLim; rel2++) {
  588.             if (rel2->Hunk == rel->Hunk) {
  589.             putl (f, rel2->Offset -    Sect->Val); /* Offset */
  590.             if (rel2 != rel)    /* Kill    hunk so    we    */
  591.                 rel2->Hunk = 0;    /*  don't do it again */
  592.             }                /*  (we're done with  */
  593.         }                /*  the    table anyway) */
  594.         }
  595.     }
  596.     NumRExt    = 0;
  597.     }
  598.     if (donexhdr)
  599.     putl (f, 0L);            /* End of external information */
  600.  
  601.     if (DumpSym) {            /* Dump    the symbol table */
  602.     donexhdr = FALSE;
  603.     for (i = 0, sym    = SymStart; i <    NumSyms; i++, sym++) {
  604.         if ((sym->Hunk == CurrHunk)
  605.         && ((sym->Flags == 0) || (sym->Flags == 2))) {
  606.         j = sym->Defn;        /* Defined in current section? */
  607.         if ((j >= SectLine) && (j <= secthlin))    {
  608.             if (!donexhdr) {
  609.             templong = HunkSym;        /* Header */
  610.             putl (f, templong);
  611.             donexhdr = TRUE;
  612.             }
  613.             DumpName (f, sym->Nam, 0L);        /* Symbol */
  614.             putl (f, sym->Val -    Sect->Val);    /* Offset */
  615.         }
  616.         }
  617.     }
  618.     if (donexhdr)
  619.         putl (f, 0L);        /* End of symbol table dump */
  620.     }
  621.  
  622.     if (HeapLim    > HighHeap)
  623.     HighHeap = HeapLim;        /* High-water mark */
  624.     HeapLim = (char *) RelStart;    /* Reset heap limit */
  625. }
  626.  
  627.  
  628.  
  629. EndSdata (f, addr) FILE    *f; long addr;
  630. /* Write end record to object file */
  631. {
  632.     register long checksum, templong;
  633.  
  634.     if (SFormat) {
  635.     DumpSdata (Srec);        /* Write any remaining data */
  636.     fprintf    (f, "S804");            /* Record header */
  637.     checksum = 4;
  638.     LongPut    (f, addr, 3);        /* Transfer address */
  639.     checksum += (addr >> 16) & 0x00FF;
  640.     checksum += (addr >> 8)    & 0x00FF;
  641.     checksum += addr & 0x00FF;
  642.     checksum = ~checksum;
  643.     LongPut    (f, checksum, 1);    /* Checksum */
  644.     fprintf    (f, "\n");
  645.     } else {
  646.     if (HunkType !=    HunkNone) {
  647.         DumpSdata (Srec);        /* Last    hunk's data */
  648.         templong = HunkEnd;        /* End the last    hunk */
  649.         putl (f, templong);
  650.     }
  651.     }
  652. }
  653.  
  654.  
  655.  
  656. DumpName (f, name, flags) FILE *f; char    name[];    long flags;
  657. /* Writes a name preceded by a long word containing the
  658.     length of the name in long words.  The length word has
  659.     the    contents of "flags" ORed into it.  The name is padded
  660.     with binary    zeros to the next long word boundary. */
  661. {
  662.     register int  i;
  663.     register long templong;
  664.  
  665.     templong = (strlen (name) +    3) >> 2;    /* Length (long    words) */
  666.     templong |=    flags;                /* Add flag bits */
  667.     putl (f, templong);
  668.     i =    0;
  669.     while (name[i])
  670.     putc (name[i++], f);            /* Write a byte    */
  671.     while (i & 3) {
  672.     putc ('\0', f);                         /* Pad the last word */
  673.     i++;
  674.     }
  675. }
  676.  
  677.  
  678.  
  679. LongPut    (f, data, length) FILE *f; long    data; int length;
  680. /* Writes to file "f" the hexadecimal interpretation of
  681.     the    bytes in "data".  The number of bytes written
  682.     (two hex digits per    byte) is given in "length" -
  683.     if less than 4, only low-order bytes are written. */
  684. {
  685.     register int  i, j,    k;
  686.  
  687.     for    (i = length - 1; i >= 0; i--) {
  688.     j = (data >> (i    * 8)) &    0x00FF;
  689.     k = j >> 4;
  690.     fprintf    (f, "%c", k>9 ? k-10+'A' : k+'0');
  691.     k = j &    0x0F;
  692.     fprintf    (f, "%c", k>9 ? k-10+'A' : k+'0');
  693.     }
  694. }
  695.  
  696.  
  697.  
  698. putl (f, data) FILE *f;    long data;
  699. /* Writes to file "f" the binary contents of "data" */
  700. {
  701.     register int  i;
  702.     register char byte;
  703.  
  704.     for    (i = 0;    i < 4; i++) {
  705.     byte = (data >>    ((3 - i) * 8)) & 0x00FF;
  706.     putc (byte, f);
  707.     }
  708. }
  709.  
  710.  
  711.  
  712. Error (pos, errornum) int pos, errornum;
  713. /* Displays error #errornum, then waits    for any    key to continue    */
  714. {
  715.     register int i;
  716.  
  717.     if (!Pass2)
  718.     return;                /* Active during pass 2    only */
  719.  
  720.     if (errlim < ERRMAX) {        /* Save    error data */
  721.     errcode[errlim]    = errornum;
  722.     errpos[errlim] = pos;
  723.     errlim++;
  724.     }
  725.     printf ("    \n%4d   %s\n", LineCount, Line);   /* Line in error */
  726.     for    (i = 0;    i < pos+7; i++)
  727.     printf(" ");
  728.     printf ("^ ");                              /* Error flag */
  729.     if (errlim == 1) {
  730.     if (InF->UPtr == 0)
  731.         printf ("%s", InF->NPtr);           /* Module name */
  732.     else
  733.         printf ("(user macro)");            /* In a user macro */
  734.     printf (" line %d", InF->Line);         /* Line number in module */
  735.     }
  736.     printf ("\n%s\n", errmsg[errornum]);        /* Error message */
  737.     ErrorCount++;                /* Count errors    */
  738. }
  739.